/**
 * ...
 * >author		João Vítor de Souza
 */

package com.cupcakeengine.core 
{
	
	import com.cupcakeengine.display.AbstractScreen;
	import com.cupcakeengine.events.EventBroadcaster;
	import com.cupcakeengine.events.ScreenEvent;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;

	public class ScreenManager extends EventDispatcher 
	{
		// ___________________________________________________________________ CONSTANTS
		
		// ___________________________________________________________________ CLASS PROPERTIES
		
		private var _dScreens			: Dictionary;
		private var _current			: AbstractScreen;
		private var _next				: AbstractScreen;
		private var _last				: AbstractScreen;
		
		// ___________________________________________________________________ INSTANCE PROPERTIES
		
		private static var _instance	: ScreenManager;
		private var _root				: Sprite;
		private var _lock				: Sprite;
		
		// ___________________________________________________________________ GETTERS AND SETTERS
		
		// ___________________________________________________________________ CONSTRUCTOR
		
		public function ScreenManager (singleton:SingletonObligate) {}
		
		// ___________________________________________________________________ PUBLIC METHODS
		
		public static function getInstance () : ScreenManager
		{
			if (!ScreenManager._instance) ScreenManager._instance = new ScreenManager(new SingletonObligate());
			return ScreenManager(ScreenManager._instance);
		}
		
		public function init(root:Sprite):void
		{
			_root = root;
			
			_dScreens = new Dictionary();	
			
			EventBroadcaster.addEventListener(ScreenEvent.TRANSITION_IN_COMPLETE, onTransitionInComplete);
			EventBroadcaster.addEventListener(ScreenEvent.TRANSITION_OUT_COMPLETE, onTransitionOutComplete);
			EventBroadcaster.addEventListener(ScreenEvent.LOCK, onScreenLock);
			EventBroadcaster.addEventListener(ScreenEvent.UNLOCK, onScreenUnlock);
		}	
		
		public function add(screen:AbstractScreen):void
		{
			_dScreens[screen.id] = screen;
		}
		
		public function remove(id:String):void
		{
			if (_dScreens == null) return;
			
			_dScreens[id] = null;
		}
		
		public function changeTo(id:String, destroyCurrentScreen:Boolean = true, buildAndChange:Boolean = true):void
		{			
			var screen:AbstractScreen = _dScreens[id]
			
			if (screen == null) return;
			
			if (_current == null) {				
				_current = _dScreens[id];
				if (buildAndChange) _current.build();
				_current.show();
			} else {				
				if (destroyCurrentScreen) {										
					_next = screen;
					if (buildAndChange) _next.build();
					_next.show();
					_current.hide();					
				} else {
					_last = _current;
					_current = screen;
					if (buildAndChange) _current.build();
					_current.show();
				}
			}

		}
		
		public function getScreenById(id:String):AbstractScreen
		{
			return _dScreens[id];
		}
		
		// ___________________________________________________________________ PRIVATE METHODS
		
		// ___________________________________________________________________ EVENTS
		
		private function onTransitionInComplete(e:ScreenEvent):void 
		{			
			var screen:AbstractScreen = _dScreens[e.id];
			
			if(_next == screen){
				_current = _next;
				_next = null;
			}
		}
		
		private function onTransitionOutComplete(e:ScreenEvent):void 
		{
			var screen:AbstractScreen = _dScreens[e.id];
			screen.destroy();
			
			if (_last != null) {
				_current = _last;
				_last = null;
			}
		}
		
		private function onScreenUnlock(e:ScreenEvent):void 
		{
			_lock.parent.removeChild(_lock);
			_lock = null;
		}
		
		private function onScreenLock(e:ScreenEvent):void 
		{
			_lock = new Sprite();
			_lock.graphics.beginFill(0x000000, 0);
			_lock.graphics.drawRect(0, 0, _root.stage.stageWidth, _root.stage.stageHeight);
			_lock.graphics.endFill();
			
			_root.stage.addChild(_lock);
		}
	}
}

class SingletonObligate {}
